Operator Precedence, Associativity, and Expression Evaluation in Python
Course: Python Training Course
Topic: Operator Precedence, Associativity, and Expression Evaluation
Course Link: Python Training Course at JustAcademy
Demo Registration: Register for a Course Demo
JustAcademy Homepage: Visit JustAcademy
1. Introduction
Python expressions often contain multiple values, operators, variables, function calls, and parentheses. When an expression contains more than one operator, Python needs rules to determine how the expression should be interpreted and evaluated.
Three important concepts help explain this process:
- Operator precedence: Determines which operators have priority over others.
- Operator associativity: Determines how operators of the same precedence are grouped when the expression does not specify another grouping.
- Expression evaluation: Describes how Python processes an expression and produces a result.
Understanding these concepts helps prevent calculation errors, makes conditional expressions easier to understand, and improves the readability and reliability of Python programs.
2. Learning Objectives
After completing this topic, you should be able to:
- Explain operator precedence and associativity.
- Understand how Python evaluates arithmetic expressions.
- Identify the precedence of arithmetic, comparison, logical, membership, identity, and bitwise operators.
- Use parentheses to control the grouping of expressions.
- Understand left-to-right and right-to-left associativity.
- Distinguish operator grouping from the order in which operands are evaluated.
- Understand short-circuit evaluation with
and and or.
- Evaluate complex expressions step by step.
- Recognize common expression-evaluation mistakes.
3. What Is an Expression in Python?
An expression is a combination of values, variables, operators, and function calls that Python can evaluate to produce a result.
Expressions may be simple, such as adding two numbers, or complex, such as combining arithmetic operations with comparisons and logical conditions.
3.1 Simple Expression
result = 10 + 5
print(result)
Output:
15
The expression 10 + 5 is evaluated to produce 15, which is assigned to the variable result.
3.2 Expression with Multiple Operators
result = 10 + 5 * 2
print(result)
Output:
20
Python performs multiplication before addition. Therefore, the expression is interpreted as 10 + (5 * 2), rather than (10 + 5) * 2.
3.3 Expression with Parentheses
result = (10 + 5) * 2
print(result)
Output:
30
Parentheses change the grouping so that addition is performed before multiplication.
4. What Is Operator Precedence?
Operator precedence is the set of rules that determines which operator binds more strongly when multiple operators appear in the same expression.
Operators with higher precedence are grouped before operators with lower precedence, unless parentheses explicitly change the grouping.
4.1 Example of Operator Precedence
result = 8 + 4 * 3
print(result)
Output:
20
Evaluation:
- Multiplication has higher precedence than addition.
- Calculate
4 * 3, which gives 12.
- Calculate
8 + 12, which gives 20.
The expression is grouped as:
8 + (4 * 3)
4.2 Changing Precedence with Parentheses
result = (8 + 4) * 3
print(result)
Output:
36
The parentheses give the addition expression priority. Python first calculates 8 + 4, then multiplies the result by 3.
5. What Is Operator Associativity?
Operator associativity determines how operators of the same precedence are grouped in an expression when the syntax does not specify another grouping.
In Python, most binary operators group from left to right. Exponentiation is an important exception because it groups from right to left. Conditional expressions also associate from right to left.
5.1 Left-to-Right Associativity
Consider the following expression:
result = 20 - 5 - 3
print(result)
Output:
12
Subtraction has left-to-right associativity. Python groups the expression as:
(20 - 5) - 3
15 - 3
12
If it were grouped differently, the result would change:
20 - (5 - 3)
20 - 2
18
This demonstrates why associativity matters for operators such as subtraction and division.
5.2 Right-to-Left Associativity
Exponentiation uses right-to-left associativity.
result = 2 ** 3 ** 2
print(result)
Output:
512
Python groups the expression as:
2 ** (3 ** 2)
2 ** 9
512
It does not group the expression as (2 ** 3) ** 2, which would produce 64.
6. Difference Between Precedence and Associativity
| Feature |
Operator Precedence |
Operator Associativity |
| Meaning |
Determines which operator binds more strongly. |
Determines grouping when operators have the same precedence. |
| When used |
When an expression contains operators with different precedence levels. |
When an expression contains operators at the same precedence level. |
| Example |
5 + 3 * 2 |
20 - 5 - 3 |
| Interpretation |
5 + (3 * 2) |
(20 - 5) - 3 |
| Purpose |
Sets operator priority. |
Sets grouping direction. |
7. Python Operator Precedence Table
The following table lists major Python operators from highest precedence to lowest precedence. Operators listed together in the same row generally share a precedence level.
| Priority |
Operators or Expressions |
Description |
Associativity or Notes |
| 1 - Highest |
(), [], {} |
Parenthesized expressions and collection displays |
Parentheses explicitly group expressions. |
| 2 |
x[index], x[index:index], x(), x.attribute |
Indexing, slicing, function calls, attribute access |
Follow Python's expression syntax. |
| 3 |
await x |
Await expression |
Used in asynchronous code. |
| 4 |
** |
Exponentiation |
Right-to-left grouping; unary-expression interaction has a special rule. |
| 5 |
+x, -x, ~x |
Unary plus, unary minus, bitwise NOT |
Unary operators. |
| 6 |
*, @, /, //, % |
Multiplication, matrix multiplication, division, floor division, remainder |
Left-to-right grouping. |
| 7 |
+, - |
Addition and subtraction |
Left-to-right grouping. |
| 8 |
<<, >> |
Bitwise shifts |
Left-to-right grouping. |
| 9 |
& |
Bitwise AND |
Left-to-right grouping. |
| 10 |
^ |
Bitwise XOR |
Left-to-right grouping. |
| 11 |
| |
Bitwise OR |
Left-to-right grouping. |
| 12 |
in, not in, is, is not, <, <=, >, >=, ==, != |
Comparisons, membership, identity |
Comparisons can be chained. |
| 13 |
not x |
Boolean NOT |
Higher precedence than and and or. |
| 14 |
and |
Boolean AND |
Lower precedence than not. |
| 15 |
or |
Boolean OR |
Lower precedence than and. |
| 16 |
x if condition else y |
Conditional expression |
Right-to-left grouping. |
| 17 |
lambda |
Lambda expression |
Low precedence. |
| 18 - Lowest |
:= |
Assignment expression (walrus operator) |
Requires attention to its expression context and syntax restrictions. |
Important: This table is a practical summary of common Python operators. For complete language rules and syntax details, consult the official Python operator precedence documentation.
8. Precedence of Arithmetic Operators
Arithmetic operators perform mathematical calculations. Their precedence determines the order of multiplication, division, addition, subtraction, and exponentiation.
| Operator |
Operation |
Example |
Result |
** |
Exponentiation |
2 ** 4 |
16 |
* |
Multiplication |
5 * 4 |
20 |
/ |
Division |
10 / 4 |
2.5 |
// |
Floor division |
10 // 4 |
2 |
% |
Remainder |
10 % 4 |
2 |
+ |
Addition |
10 + 4 |
14 |
- |
Subtraction |
10 - 4 |
6 |
Exponentiation has higher precedence than unary minus in the expression -2 ** 2.
print(-2 ** 2)
print((-2) ** 2)
Output:
-4
4
The first expression is interpreted as -(2 ** 2). In the second expression, parentheses make the negative number the base of the exponentiation.
9. Evaluating Arithmetic Expressions Step by Step
When evaluating a complex arithmetic expression, identify the grouping and apply the operators in the correct order.
Example 1: Multiplication Before Addition
result = 10 + 6 * 2
print(result)
Step-by-step evaluation:
- Calculate
6 * 2 = 12.
- Calculate
10 + 12 = 22.
Output: 22
Example 2: Parentheses and Division
result = (18 + 6) / 4
print(result)
Step-by-step evaluation:
- Evaluate the parentheses:
18 + 6 = 24.
- Divide the result by four:
24 / 4 = 6.0.
Output: 6.0
Example 3: Combined Arithmetic Operations
result = 30 - 4 * 3 + 8 / 2
print(result)
Step-by-step evaluation:
- Calculate
4 * 3 = 12.
- Calculate
8 / 2 = 4.0.
- Evaluate the remaining addition and subtraction from left to right:
30 - 12 + 4.0.
- Calculate
18 + 4.0 = 22.0.
Output: 22.0
10. Precedence of Comparison Operators
Comparison operators compare values and produce Boolean results in ordinary comparisons. These operators include ==, !=, <, >, <=, and >=.
result = 5 + 3 > 6
print(result)
Output:
True
Python evaluates 5 + 3 first, producing 8, and then evaluates 8 > 6.
10.1 Chained Comparisons
Python allows multiple comparisons to be chained together.
age = 25
print(18 <= age <= 60)
Output:
True
The expression checks whether age is greater than or equal to 18 and less than or equal to 60. It behaves like 18 <= age and age <= 60, with the middle expression evaluated only once.
11. Precedence of Logical Operators
Python provides three main Boolean logical operators:
not – Reverses the truth value of an expression.
and – Evaluates to a truthy or falsy operand based on whether both sides are truthy.
or – Evaluates to a truthy or falsy operand based on whether at least one side is truthy.
For Boolean conditions, the precedence order is:
not > and > or
11.1 Example Using Logical Precedence
result = True or False and False
print(result)
Output:
True
The and operator has higher precedence than or. The expression is grouped as True or (False and False), which evaluates to True.
11.2 Using Parentheses for Clarity
has_id = True
is_registered = False
is_admin = False
result = has_id and (is_registered or is_admin)
print(result)
Output:
False
The parentheses group the registration and administrator checks together. Since both are false, the overall condition is false.
12. Short-Circuit Evaluation
Short-circuit evaluation occurs when Python can determine the result of a logical expression without evaluating every part of it.
- With
and, if the first operand is falsy, Python does not evaluate the second operand.
- With
or, if the first operand is truthy, Python does not evaluate the second operand.
In Python, and and or return one of their operands rather than always returning a Boolean value. In an if condition, their truthiness determines the branch taken.
12.1 Short-Circuit with and
number = 0
result = number != 0 and 10 / number > 2
print(result)
Output:
False
Because number != 0 is false, Python does not evaluate 10 / number. This prevents a division-by-zero error.
12.2 Short-Circuit with or
username = "admin"
result = username == "admin" or 10 / 0 > 1
print(result)
Output:
True
The first condition is true, so Python does not evaluate the second operand. Consequently, the division by zero does not occur.
13. Expression Evaluation Order
Operator precedence and associativity determine how an expression is grouped. Expression evaluation order describes the order in which Python evaluates its components.
Python generally evaluates expressions from left to right. However, the evaluation order does not mean that every operator is applied from left to right. Precedence and associativity still determine how operators are grouped.
result = 10 + 2 * 3
print(result)
Python evaluates the operands according to the language's evaluation rules, while the multiplication operator binds more strongly than addition. Therefore, the result is 16.
13.1 Function Calls and Argument Evaluation
Function arguments are evaluated before the function receives their values. In an ordinary function call, argument expressions are evaluated from left to right.
def show_values(a, b):
print(a, b)
def get_first():
print("First argument")
return 10
def get_second():
print("Second argument")
return 20
show_values(get_first(), get_second())
Output:
First argument
Second argument
10 20
This example demonstrates left-to-right evaluation of the two argument expressions.
13.2 Assignment Evaluation
In assignment statements, Python evaluates the right-hand side before assigning the result to the target.
x = 10
x = x + 5
print(x)
Output:
15
Python evaluates x + 5 using the current value of x, then assigns the result to x.
14. Understanding Associativity with Different Operators
14.1 Addition and Subtraction
print(10 - 3 - 2)
print(10 - (3 - 2))
Output:
5
9
Subtraction is not associative in the mathematical sense. Parentheses can change the result.
14.2 Multiplication and Division
print(24 / 6 * 2)
print(24 / (6 * 2))
Output:
8.0
2.0
Multiplication and division share a precedence level and group from left to right. Parentheses can change the grouping and result.
14.3 Exponentiation
print(3 ** 2 ** 2)
print((3 ** 2) ** 2)
Output:
81
81
In this particular example, both expressions produce the same result because the powers happen to give 81. A better example of the difference is:
print(2 ** 3 ** 2)
print((2 ** 3) ** 2)
Output:
512
64
The first expression groups from the right, while the second explicitly groups from the left.
15. Bitwise Operator Precedence
Bitwise operators manipulate the binary representation of integers. They also have defined precedence levels, which matter when they appear with arithmetic or comparison operators.
| Operator |
Meaning |
Relative Precedence |
<<, >> |
Left and right shifts |
Higher than bitwise AND |
& |
Bitwise AND |
Higher than XOR and OR |
^ |
Bitwise XOR |
Higher than bitwise OR |
| |
Bitwise OR |
Lower than AND and XOR |
result = 2 + 3 & 7
print(result)
Output:
5
Addition has higher precedence than bitwise AND. Python groups this expression as (2 + 3) & 7, which evaluates to 5 & 7, producing 5.
When combining bitwise operators with arithmetic or comparisons, use parentheses to make the intended order explicit.
16. Conditional Expressions and Precedence
A conditional expression selects one of two values based on a condition. Its syntax is:
value_if_true if condition else value_if_false
Example:
age = 20
category = "Adult" if age >= 18 else "Minor"
print(category)
Output:
Adult
The condition age >= 18 determines which value is selected. Conditional expressions are useful for simple choices, but complex nested expressions are often easier to understand with regular if statements.
17. Nested Parentheses and Expression Grouping
Parentheses can be nested to control the order of evaluation. Python evaluates the innermost grouped expression first.
result = ((5 + 3) * (10 - 4)) / 2
print(result)
Step-by-step evaluation:
- Evaluate
5 + 3 = 8.
- Evaluate
10 - 4 = 6.
- Multiply
8 * 6 = 48.
- Divide
48 / 2 = 24.0.
Output:
24.0
Use nested parentheses carefully. Too many unnecessary parentheses can make an expression harder to read, while well-placed parentheses make complex expressions clearer.
18. Common Mistakes in Expression Evaluation
| Mistake |
Why It Happens |
Correct Approach |
| Assuming addition happens before multiplication |
Ignoring operator precedence. |
Remember that multiplication and division have higher precedence than addition and subtraction. |
| Assuming every operator groups left to right |
Overlooking right-associative operators. |
Remember that exponentiation and conditional expressions group from right to left. |
Using is to compare values |
Confusing object identity with equality. |
Use == for value comparisons. |
| Misreading logical expressions |
Forgetting the precedence of not, and, and or. |
Use parentheses to make the intended grouping explicit. |
Expecting and and or to always return Booleans |
Assuming they only return True or False. |
Remember that they return operands according to their truthiness and short-circuit rules. |
| Ignoring short-circuit behavior |
Assuming all operands are always evaluated. |
Understand when Python skips evaluation of the second operand. |
| Writing expressions that are too complex |
Trying to fit too many operations into one line. |
Break the expression into intermediate variables. |
| Confusing evaluation order with associativity |
Treating both concepts as identical. |
Distinguish the order of evaluating components from operator grouping. |
19. Best Practices for Writing Clear Expressions
- Use parentheses when an expression contains several different operators.
- Keep expressions short enough to understand at a glance.
- Use meaningful variable names instead of unexplained numeric values.
- Break complicated calculations into intermediate variables.
- Use
== for value equality and is None for checking None.
- Use parentheses around logical conditions when they improve readability.
- Understand short-circuit evaluation before relying on it to prevent errors.
- Avoid deeply nested conditional expressions.
- Follow consistent spacing around operators.
- Test expressions with typical values, boundary values, and unexpected inputs.
20. Practical Example: Calculating a Student's Result
This example combines arithmetic, comparison, logical operators, and parentheses to calculate a student's average and determine whether the student passes.
math_marks = 75
science_marks = 82
english_marks = 68
total = math_marks + science_marks + english_marks
average = total / 3
passed = (
math_marks >= 40
and science_marks >= 40
and english_marks >= 40
and average >= 50
)
print("Total:", total)
print("Average:", average)
print("Passed:", passed)
Output:
Total: 225
Average: 75.0
Passed: True
Explanation
- Addition calculates the total marks.
- Division calculates the average.
- Comparison operators check each subject's marks and the average.
- The
and operator requires every condition to be true.
- Parentheses make the complete pass condition easier to read.
21. Practical Example: Product Discount Calculator
The following program calculates a discounted price using arithmetic operations and a conditional expression.
price = 2000
discount_percent = 15
discount = price * discount_percent / 100
final_price = price - discount
status = "Discount applied" if discount_percent > 0 else "No discount"
print("Original price:", price)
print("Discount:", discount)
print("Final price:", final_price)
print(status)
Output:
Original price: 2000
Discount: 300.0
Final price: 1700.0
Discount applied
The program first calculates the discount, then subtracts it from the original price. The conditional expression selects a message according to the discount percentage.
22. Debugging Expressions
When an expression produces an unexpected result, use a systematic approach to identify the problem.
- Identify all the operators in the expression.
- Check the precedence of each operator.
- Determine how operators with equal precedence are grouped.
- Inspect parentheses and nested expressions.
- Check the data types of the operands.
- Consider whether logical short-circuiting changes which expressions are evaluated.
- Print intermediate results or assign them to temporary variables.
- Test the expression with simpler values.
For example, instead of writing:
result = price - price * discount / 100 + fee
you can make the calculation easier to understand by writing:
discount_amount = price * discount / 100
discounted_price = price - discount_amount
result = discounted_price + fee
Both versions follow Python's expression rules, but the second version makes the calculation stages more explicit.
23. Practice Exercises
Exercise 1: Arithmetic Precedence
Predict the output before running the code.
print(5 + 4 * 3)
Exercise 2: Parentheses
print((5 + 4) * 3)
Exercise 3: Associativity
print(40 - 10 - 5)
print(40 - (10 - 5))
Exercise 4: Exponentiation
print(2 ** 2 ** 3)
print((2 ** 2) ** 3)
Exercise 5: Logical Precedence
print(True or False and False)
print((True or False) and False)
Exercise 6: Comparison and Arithmetic
number = 8
print(number + 2 > 9)
Exercise 7: Short-Circuit Evaluation
value = 0
print(value != 0 and 100 / value > 1)
Exercise 8: Student Eligibility
Create a program that calculates a student's average and checks whether the average is at least 50 and every subject mark is at least 35.
Exercise 9: Discount Calculation
Write a program that calculates a discount and final price. Use parentheses or intermediate variables to make the calculation easy to follow.
Exercise 10: Complex Expression
Write a program that combines arithmetic, comparison, and logical operators. Explain the order in which Python evaluates the expression.
24. Interview Questions and Answers
Q1. What is operator precedence in Python?
Answer: Operator precedence determines which operators bind more strongly when an expression contains multiple operators.
Q2. What is operator associativity?
Answer: Associativity determines how operators of the same precedence are grouped when parentheses or other syntax do not specify a different grouping.
Q3. What is the difference between precedence and associativity?
Answer: Precedence determines priority between different operator levels. Associativity determines grouping between operators at the same precedence level.
Q4. What is the output of 5 + 3 * 2?
Answer: 11. Multiplication occurs before addition, so Python calculates 5 + 6.
Q5. How does Python evaluate 2 ** 3 ** 2?
Answer: Exponentiation groups from right to left, so the expression is 2 ** (3 ** 2), which equals 512.
Q6. Why are parentheses useful?
Answer: Parentheses override the default grouping, make complex expressions easier to understand, and help communicate the programmer's intent.
Q7. What is short-circuit evaluation?
Answer: Short-circuit evaluation allows Python to stop evaluating a logical expression when the result is already determined by the first operand.
Q8. What is the precedence order of not, and, and or?
Answer: The precedence order is not, then and, then or, from highest to lowest.
Q9. Does Python always evaluate every operand in a logical expression?
Answer: No. The and and or operators can skip evaluating the second operand when the result is already determined.
Q10. What is the difference between expression evaluation order and associativity?
Answer: Evaluation order describes when parts of an expression are evaluated. Associativity describes how operators of the same precedence are grouped.
Q11. How are chained comparisons evaluated?
Answer: An expression such as 10 < x < 20 checks both comparisons and evaluates the middle expression only once. It is equivalent to 10 < x and x < 20.
Q12. What is the precedence of multiplication compared with addition?
Answer: Multiplication has higher precedence than addition, so multiplication is grouped first unless parentheses change the grouping.
25. Quick Revision Notes
- Operator precedence determines which operators bind more strongly.
- Associativity determines grouping when operators share a precedence level.
- Parentheses can override default operator grouping.
- Multiplication, division, floor division, and remainder have higher precedence than addition and subtraction.
- Exponentiation groups from right to left.
- Unary minus has lower precedence than exponentiation in expressions such as
-2 ** 2.
- Comparison, membership, and identity operators share a precedence level.
- Boolean precedence is
not before and before or.
- Python generally evaluates expression components from left to right.
- Assignment evaluates the right-hand side before assigning to the target.
and and or use short-circuit evaluation.
- Clear parentheses and intermediate variables make complicated expressions easier to debug.
26. Conclusion
Operator precedence, associativity, and expression evaluation are fundamental concepts in Python programming. Precedence establishes the relative priority of operators, associativity determines how operators at the same precedence level are grouped, and evaluation order describes how Python processes expressions.
By learning these rules and practicing arithmetic, comparison, bitwise, and logical expressions, you can predict program results more accurately and avoid common mistakes. Although Python defines consistent rules, using meaningful variable names, parentheses, and intermediate calculations is often the best way to make your code readable and maintainable.
Continue Learning: Explore the Python Training Course at JustAcademy, register for a course demo, or visit the JustAcademy homepage.